A segmentação de imagens, um dos procedimentos mais básicos em visão computacional, permite que um sistema decomponha e analise várias regiões dentro de uma imagem. Quer você esteja lidando com reconhecimento de objetos, imagens médicas ou direção autônoma, a segmentação é o que divide as imagens em partes significativas.
Embora os modelos de aprendizagem profunda continuem a ser cada vez mais populares nesta tarefa, as técnicas tradicionais de processamento digital de imagens ainda são poderosas e práticas. As abordagens revisadas nesta postagem incluem limiar, detecção de borda, baseada em região e agrupamento, implementando um conjunto de dados bem reconhecido para a análise de imagens de células, o conjunto de dados de imagens MIVIA HEp-2.
O conjunto de dados de imagens MIVIA HEp-2 é um conjunto de imagens de células usadas para analisar o padrão de anticorpos antinucleares (ANA) através de células HEp-2. Consiste em fotos 2D tiradas por microscopia de fluorescência. Isso o torna muito adequado para tarefas de segmentação, principalmente aquelas relacionadas à análise de imagens médicas, onde a detecção de regiões celulares é mais importante.
Agora, vamos passar para as técnicas de segmentação usadas para processar essas imagens, comparando seu desempenho com base nas pontuações da F1.
Limiar é o processo pelo qual imagens em tons de cinza são convertidas em imagens binárias com base nas intensidades de pixel. No conjunto de dados MIVIA HEp-2, este processo é útil na extração de células do fundo. É simples e eficaz em um nível relativamente grande, especialmente com o método de Otsu, pois ele auto-calcula o limite ideal.
Método de Otsu é um método de limiarização automática, onde tenta encontrar o melhor valor de limiar para produzir a variância intraclasse mínima, separando assim as duas classes: primeiro plano (células) e fundo. O método examina o histograma da imagem e calcula o limite perfeito, onde a soma das variações de intensidade de pixel em cada classe é minimizada.
# Thresholding Segmentation def thresholding(img): # Convert image to grayscale gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Apply Otsu's thresholding _, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY cv.THRESH_OTSU) return thresh
A detecção de bordas refere-se à identificação de limites de objetos ou regiões, como bordas de células no conjunto de dados MIVIA HEp-2. Dos muitos métodos disponíveis para detectar mudanças abruptas de intensidade, o Canny Edge Detector é o melhor e, portanto, o método mais apropriado para ser usado para detectar limites celulares.
Canny Edge Detector é um algoritmo de vários estágios que pode detectar as bordas detectando áreas de fortes gradientes de intensidade. O processo incorpora suavização com filtro gaussiano, cálculo de gradientes de intensidade, aplicação de supressão não máxima para eliminar respostas espúrias e uma operação final de limiar duplo para a retenção apenas de bordas salientes.
# Edge Detection Segmentation def edge_detection(img): # Convert image to grayscale gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Apply Gaussian blur gray = cv.GaussianBlur(gray, (3, 3), 0) # Calculate lower and upper thresholds for Canny edge detection sigma = 0.33 v = np.median(gray) lower = int(max(0, (1.0 - sigma) * v)) upper = int(min(255, (1.0 sigma) * v)) # Apply Canny edge detection edges = cv.Canny(gray, lower, upper) # Dilate the edges to fill gaps kernel = np.ones((5, 5), np.uint8) dilated_edges = cv.dilate(edges, kernel, iterations=2) # Clean the edges using morphological opening cleaned_edges = cv.morphologyEx(dilated_edges, cv.MORPH_OPEN, kernel, iterations=1) # Find connected components and filter out small components num_labels, labels, stats, _ = cv.connectedComponentsWithStats( cleaned_edges, connectivity=8 ) min_size = 500 filtered_mask = np.zeros_like(cleaned_edges) for i in range(1, num_labels): if stats[i, cv.CC_STAT_AREA] >= min_size: filtered_mask[labels == i] = 255 # Find contours of the filtered mask contours, _ = cv.findContours( filtered_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE ) # Create a filled mask using the contours filled_mask = np.zeros_like(gray) cv.drawContours(filled_mask, contours, -1, (255), thickness=cv.FILLED) # Perform morphological closing to fill holes final_filled_image = cv.morphologyEx( filled_mask, cv.MORPH_CLOSE, kernel, iterations=2 ) # Dilate the final filled image to smooth the edges final_filled_image = cv.dilate(final_filled_image, kernel, iterations=1) return final_filled_image
Segmentação de bacias hidrográficas pode ser usada para ajudar na segmentação de imagens de células HEp-2 para poder detectar as regiões que representam células; considera as intensidades dos pixels como uma superfície topográfica e delineia regiões distintas.
Segmentação de bacias hidrográficas trata as intensidades dos pixels como uma superfície topográfica. O algoritmo identifica "bacias" nas quais identifica mínimos locais e depois inunda gradualmente essas bacias para ampliar regiões distintas. Esta técnica é bastante útil quando se deseja separar objetos tocantes, como no caso de células em imagens microscópicas, mas pode ser sensível ao ruído. O processo pode ser guiado por marcadores e a segmentação excessiva muitas vezes pode ser reduzida.
# Edge Detection Segmentation def edge_detection(img): # Convert image to grayscale gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Apply Gaussian blur gray = cv.GaussianBlur(gray, (3, 3), 0) # Calculate lower and upper thresholds for Canny edge detection sigma = 0.33 v = np.median(gray) lower = int(max(0, (1.0 - sigma) * v)) upper = int(min(255, (1.0 sigma) * v)) # Apply Canny edge detection edges = cv.Canny(gray, lower, upper) # Dilate the edges to fill gaps kernel = np.ones((5, 5), np.uint8) dilated_edges = cv.dilate(edges, kernel, iterations=2) # Clean the edges using morphological opening cleaned_edges = cv.morphologyEx(dilated_edges, cv.MORPH_OPEN, kernel, iterations=1) # Find connected components and filter out small components num_labels, labels, stats, _ = cv.connectedComponentsWithStats( cleaned_edges, connectivity=8 ) min_size = 500 filtered_mask = np.zeros_like(cleaned_edges) for i in range(1, num_labels): if stats[i, cv.CC_STAT_AREA] >= min_size: filtered_mask[labels == i] = 255 # Find contours of the filtered mask contours, _ = cv.findContours( filtered_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE ) # Create a filled mask using the contours filled_mask = np.zeros_like(gray) cv.drawContours(filled_mask, contours, -1, (255), thickness=cv.FILLED) # Perform morphological closing to fill holes final_filled_image = cv.morphologyEx( filled_mask, cv.MORPH_CLOSE, kernel, iterations=2 ) # Dilate the final filled image to smooth the edges final_filled_image = cv.dilate(final_filled_image, kernel, iterations=1) return final_filled_image
K-Means tendem a agrupar os pixels em clusters semelhantes, o que funciona bem quando se deseja segmentar células em ambientes multicoloridos ou complexos, como visto em imagens de células HEp-2. Fundamentalmente, isso poderia representar diferentes classes, como uma região celular versus um plano de fundo.
K-means é um algoritmo de aprendizado não supervisionado para agrupar imagens com base na similaridade de pixel de cor ou intensidade. O algoritmo seleciona aleatoriamente K centróides, atribui cada pixel ao centróide mais próximo e atualiza o centróide iterativamente até convergir. É particularmente eficaz na segmentação de uma imagem que possui múltiplas regiões de interesse muito diferentes umas das outras.
# Edge Detection Segmentation def edge_detection(img): # Convert image to grayscale gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Apply Gaussian blur gray = cv.GaussianBlur(gray, (3, 3), 0) # Calculate lower and upper thresholds for Canny edge detection sigma = 0.33 v = np.median(gray) lower = int(max(0, (1.0 - sigma) * v)) upper = int(min(255, (1.0 sigma) * v)) # Apply Canny edge detection edges = cv.Canny(gray, lower, upper) # Dilate the edges to fill gaps kernel = np.ones((5, 5), np.uint8) dilated_edges = cv.dilate(edges, kernel, iterations=2) # Clean the edges using morphological opening cleaned_edges = cv.morphologyEx(dilated_edges, cv.MORPH_OPEN, kernel, iterations=1) # Find connected components and filter out small components num_labels, labels, stats, _ = cv.connectedComponentsWithStats( cleaned_edges, connectivity=8 ) min_size = 500 filtered_mask = np.zeros_like(cleaned_edges) for i in range(1, num_labels): if stats[i, cv.CC_STAT_AREA] >= min_size: filtered_mask[labels == i] = 255 # Find contours of the filtered mask contours, _ = cv.findContours( filtered_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE ) # Create a filled mask using the contours filled_mask = np.zeros_like(gray) cv.drawContours(filled_mask, contours, -1, (255), thickness=cv.FILLED) # Perform morphological closing to fill holes final_filled_image = cv.morphologyEx( filled_mask, cv.MORPH_CLOSE, kernel, iterations=2 ) # Dilate the final filled image to smooth the edges final_filled_image = cv.dilate(final_filled_image, kernel, iterations=1) return final_filled_image
pontuação F1 é uma medida que combina precisão e recall para comparar a imagem de segmentação prevista com a imagem real. É a média harmônica de precisão e recuperação, útil em casos de alto desequilíbrio de dados, como em conjuntos de dados de imagens médicas.
Calculamos a pontuação F1 para cada método de segmentação nivelando a verdade básica e a imagem segmentada e calculando a pontuação F1 ponderada.
# Edge Detection Segmentation def edge_detection(img): # Convert image to grayscale gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # Apply Gaussian blur gray = cv.GaussianBlur(gray, (3, 3), 0) # Calculate lower and upper thresholds for Canny edge detection sigma = 0.33 v = np.median(gray) lower = int(max(0, (1.0 - sigma) * v)) upper = int(min(255, (1.0 sigma) * v)) # Apply Canny edge detection edges = cv.Canny(gray, lower, upper) # Dilate the edges to fill gaps kernel = np.ones((5, 5), np.uint8) dilated_edges = cv.dilate(edges, kernel, iterations=2) # Clean the edges using morphological opening cleaned_edges = cv.morphologyEx(dilated_edges, cv.MORPH_OPEN, kernel, iterations=1) # Find connected components and filter out small components num_labels, labels, stats, _ = cv.connectedComponentsWithStats( cleaned_edges, connectivity=8 ) min_size = 500 filtered_mask = np.zeros_like(cleaned_edges) for i in range(1, num_labels): if stats[i, cv.CC_STAT_AREA] >= min_size: filtered_mask[labels == i] = 255 # Find contours of the filtered mask contours, _ = cv.findContours( filtered_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE ) # Create a filled mask using the contours filled_mask = np.zeros_like(gray) cv.drawContours(filled_mask, contours, -1, (255), thickness=cv.FILLED) # Perform morphological closing to fill holes final_filled_image = cv.morphologyEx( filled_mask, cv.MORPH_CLOSE, kernel, iterations=2 ) # Dilate the final filled image to smooth the edges final_filled_image = cv.dilate(final_filled_image, kernel, iterations=1) return final_filled_imageEm seguida, visualizamos as pontuações F1 de diferentes métodos usando um gráfico de barras simples:
Cada método tem sua força:
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3